using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.IO;
using System.Net;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace Channelvn.Storage
{
    public class ChannelvnStorage
    {
        /// <summary>
        /// Upload a file from a web url to storage system
        /// </summary>
        /// <param name="imageUrl"></param>
        /// <returns>If success this function will be return full path of upload image. If fail it return null.</returns>
        public string UploadFile(string imageUrl, string imagePath, string fileName, ref string result, ref string errorMess)
        {
            try
            {
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(imageUrl);
                HttpWebResponse res = (HttpWebResponse)req.GetResponse();
                Stream myStream = res.GetResponseStream();
                int contentLength = (int)res.ContentLength;
                if (contentLength == 0) return null;

                string secretKey = ConfigurationManager.AppSettings["SecretKey"];
                string prefix = ConfigurationManager.AppSettings["Prefix"];
                string keyUpload = ConfigurationManager.AppSettings["keyUpload"];
                string imageHost = ConfigurationManager.AppSettings["ImageServer"];
                string readImageHost = ConfigurationManager.AppSettings["ReadImageServer"];

                string url = imageHost + keyUpload;

                //string baseFolder = Utils.GetFolder(imagePath, prefix);
                string baseFolder = string.Empty;

                if (!string.Empty.Equals(prefix))
                {
                    baseFolder = Utils.GetFolder(imagePath, prefix);
                    imagePath = (imagePath.StartsWith(prefix) ? imagePath : string.Format("{0}{1}", prefix, string.IsNullOrEmpty(imagePath) ? "" : "/" + imagePath));
                }
                else {
                    baseFolder = imagePath;                    
                }                

                const int readSize = 256;
                byte[] buffer = new byte[readSize];
                MemoryStream ms = new MemoryStream();
                int count = myStream.Read(buffer, 0, readSize);
                while (count > 0)
                {
                    ms.Write(buffer, 0, count);
                    count = myStream.Read(buffer, 0, readSize);
                }
                ms.Seek(0, SeekOrigin.Begin);
                long len = ms.Length;
                byte[] data = new byte[len];
                ms.Read(data, 0, (int)len);
                // Generate post objects
                Dictionary<string, object> postParameters = new Dictionary<string, object>();
                postParameters.Add("secret_key", secretKey);
                postParameters.Add("filename", imagePath);
                postParameters.Add("filedata", new FormUpload.FileParameter(data, imagePath, "application/octet-stream"));

                string postURL = url;
                string userAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1";
                HttpWebResponse webResponse = FormUpload.MultipartFormDataPost(postURL, userAgent, postParameters, ref result, ref errorMess, fileName);

                // Process response
                if (webResponse != null)
                {
                    StreamReader responseReader = new StreamReader(webResponse.GetResponseStream());
                    string fullResponse = responseReader.ReadToEnd();
                    webResponse.Close();                    
                    return readImageHost + baseFolder;
                }
                return null;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
     
        /// <summary>
        /// Upload a file to storage system.
        /// </summary>
        /// <param name="fileName">File will be upload</param>
        /// <param name="fu">Struct of file will be upload</param>
        /// <param name="result">Status of uploaded file</param>
        /// <returns>If success this function will be return full path of upload image. If fail it return null.</returns>
        public string UploadFile(string fileName, HttpPostedFile fu, ref string result, ref string errorMess)
        {
            try
            {
                fu.InputStream.Seek(0, SeekOrigin.Begin);
                if (fu.ContentLength == 0) return "";

                string secretKey = ConfigurationManager.AppSettings["SecretKey"];
                string prefix = ConfigurationManager.AppSettings["Prefix"];
                //string baseFolder = Utils.GetFolder(fileName, prefix);
                string baseFolder = string.Empty;

                if (!string.Empty.Equals(prefix))
                {
                    baseFolder = Utils.GetFolder(fileName, prefix);
                    fileName = (fileName.StartsWith(prefix) ? fileName : string.Format("{0}{1}", prefix, string.IsNullOrEmpty(fileName) ? "" : "/" + fileName));
                }
                else {
                    baseFolder = fileName;
                }

                string keyUpload = ConfigurationManager.AppSettings["keyUpload"];
                string imageHost = ConfigurationManager.AppSettings["ImageServer"];
                string readImageHost = ConfigurationManager.AppSettings["ReadImageServer"];

                string url = imageHost + keyUpload;

                byte[] data = new byte[fu.ContentLength];
                Stream myStream = fu.InputStream;
                myStream.Read(data, 0, fu.ContentLength);

                // Generate post objects
                Dictionary<string, object> postParameters = new Dictionary<string, object>();
                postParameters.Add("secret_key", secretKey);
                //postParameters.Add("filename", fileName + "/" + fu.FileName);
                postParameters.Add("filename", fileName);
                //postParameters.Add("filedata", new FormUpload.FileParameter(data, fileName + "/" + fu.FileName, fu.ContentType));
                postParameters.Add("filedata", new FormUpload.FileParameter(data, fileName, fu.ContentType));

                string postURL = url;
                string userAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1";
                HttpWebResponse webResponse = FormUpload.MultipartFormDataPost(postURL, userAgent, postParameters, ref result, ref errorMess, fu.FileName);

                // Process response
                if (webResponse != null)
                {
                    StreamReader responseReader = new StreamReader(webResponse.GetResponseStream());
                    string fullResponse = responseReader.ReadToEnd();
                    webResponse.Close();
                    //return readImageHost + baseFolder + "/" + fu.FileName;
                    return readImageHost + baseFolder;
                }
                return null;
            }
            catch (Exception ex) {
                throw ex;                
            }
        }
        
        /**
        /// <summary>
        /// Get information of a directory in storage system.
        /// </summary>
        /// <param name="dirName">Directory need to get information.</param>
        /// <param name="includePrefix">true: the fileName will be attache a prefix string</param>
        /// <returns>Object contain information of this directory.</returns>
        public ChannelvnDirInfo ListDir(string dirName, bool includePrefix)
        {
            string imageHost = ConfigurationManager.AppSettings["ImageServer"];
            string keyUpload = ConfigurationManager.AppSettings["keyListDir"];
            string secretKey = ConfigurationManager.AppSettings["SecretKey"];
            string prefix = ConfigurationManager.AppSettings["Prefix"];

            string baseUri = imageHost + keyUpload;

            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(baseUri + "?secret_key=" + secretKey + "&dirname=" + (includePrefix ? string.Format("{0}/{1}", prefix, dirName):dirName));            
            webRequest.ContentType = "application/x-www-form-urlencoded";
            webRequest.Method = "GET";                               

            try
            { // get the response
                WebResponse webResponse = webRequest.GetResponse();                
                if (webResponse == null)
                { return null; }
                StreamReader sr = new StreamReader(webResponse.GetResponseStream());
                string result = sr.ReadToEnd().Trim();
                return Utils.ConvertToDirectorObj(result);
            }
            catch (WebException ex)
            {
                HttpStatusCode status = ((HttpWebResponse)ex.Response).StatusCode;
                //Console.WriteLine("Error..... " + ex.StackTrace);
                throw ex;
            }            
        }
        /**/


        /// <summary>
        /// Get information of a directory in storage system.
        /// </summary>
        /// <param name="dirName">Directory need to get information.</param>
        /// <param name="order">order=1 or order=0 to sort desc or asc</param>
        /// <param name="sortBy">sort by time or name</param>
        /// <param name="includePrefix">true: the fileName will be attache a prefix string</param>
        /// <returns>Object contain information of this directory.</returns>
        public ChannelvnDirInfo ListDir(string dirName, int order, string sortBy, bool includePrefix)
        {
            string imageHost = ConfigurationManager.AppSettings["ImageServer"];
            string keyListDir = ConfigurationManager.AppSettings["keyListDir"];
            string secretKey = ConfigurationManager.AppSettings["SecretKey"];
            string prefix = ConfigurationManager.AppSettings["Prefix"];

            string baseUri = imageHost + keyListDir;

            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(baseUri + "?secret_key=" + secretKey + 
                                         "&dirname=" + (includePrefix ? string.Format("{0}/{1}", prefix, dirName) : dirName) +
                                         "&reverse=" + order + "&sort_by=" + sortBy);
            webRequest.ContentType = "application/x-www-form-urlencoded";
            webRequest.Method = "GET";

            try
            { // get the response
                WebResponse webResponse = webRequest.GetResponse();
                if (webResponse == null)
                { return null; }
                StreamReader sr = new StreamReader(webResponse.GetResponseStream());
                string result = sr.ReadToEnd().Trim();
                return Utils.ConvertToDirectorObj(result);
            }
            catch (WebException ex)
            {
                HttpStatusCode status = ((HttpWebResponse)ex.Response).StatusCode;                
                
                //Console.WriteLine("Error..... " + ex.StackTrace);
                //throw ex;
                return null;
            }
        }

        public string MakeDir(string dirName, bool includePrefix) {
            string imageHost = ConfigurationManager.AppSettings["ImageServer"];
            string keyMakeDir = ConfigurationManager.AppSettings["keyMakeDir"];
            string secretKey = ConfigurationManager.AppSettings["SecretKey"];
            string prefix = ConfigurationManager.AppSettings["Prefix"];

            string baseUri = imageHost + keyMakeDir;
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(baseUri + "?secret_key=" + secretKey +
                                            "&dirname=" + (includePrefix ? string.Format("{0}/{1}", prefix, dirName) : dirName));
            webRequest.ContentType = "application/x-www-form-urlencoded";
            webRequest.Method = "GET";
            try
            { // get the response
                WebResponse webResponse = webRequest.GetResponse();
                if (webResponse == null)
                { return null; }
                StreamReader sr = new StreamReader(webResponse.GetResponseStream());
                string result = sr.ReadToEnd().Trim();
                return result;
            }
            catch (WebException ex)
            {
                HttpStatusCode status = ((HttpWebResponse)ex.Response).StatusCode;
                //Console.WriteLine("Error..... " + ex.StackTrace);
                return status.ToString();
            }
        }

        public string RemoveDir(string dirName, bool includePrefix) {
            string imageHost = ConfigurationManager.AppSettings["ImageServer"];
            string keyRemoveDir = ConfigurationManager.AppSettings["keyRemoveDir"];
            string secretKey = ConfigurationManager.AppSettings["SecretKey"];
            string prefix = ConfigurationManager.AppSettings["Prefix"];

            string baseUri = imageHost + keyRemoveDir;
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(baseUri + "?secret_key=" + secretKey +
                                            "&dirname=" + (includePrefix ? string.Format("{0}/{1}", prefix, dirName) : dirName));
            webRequest.ContentType = "application/x-www-form-urlencoded";
            webRequest.Method = "GET";
            try
            { // get the response
                WebResponse webResponse = webRequest.GetResponse();
                if (webResponse == null)
                { return null; }
                StreamReader sr = new StreamReader(webResponse.GetResponseStream());
                string result = sr.ReadToEnd().Trim();
                return result;
            }
            catch (WebException ex)
            {
                HttpStatusCode status = ((HttpWebResponse)ex.Response).StatusCode;
                //Console.WriteLine("Error..... " + ex.StackTrace);
                return status.ToString();
            }
        }
        
        /// <summary>
        /// This function remove a file from storage system.
        /// </summary>
        /// <param name="fileName">The file name will be remove</param>
        /// <param name="includePrefix">true: the fileName will be attache a prefix string</param>
        /// <returns>If success this function will return OK string</returns>
        public string DeleteFile(string fileName, bool includePrefix)
        {           
            try
            {
                string secretKey = ConfigurationManager.AppSettings["SecretKey"];
                string imageHost = ConfigurationManager.AppSettings["ImageServer"];
                string prefix = ConfigurationManager.AppSettings["Prefix"];

                string keyDelete = ConfigurationManager.AppSettings["keyDelete"];
                DownloadExpress down = new DownloadExpress(imageHost + keyDelete + "?secret_key=" + secretKey + "&filename=" + (includePrefix ? string.Format("{0}/{1}", prefix, fileName) : fileName));
                string ad = down.GetHtmlData();
                return ad;
            }
            catch (Exception ex) {
                throw ex;                
            }
        }
        
        /// <summary>
        /// Rename or moving file from a folder to another folder.
        /// </summary>
        /// <param name="oldFileName">Old file name.</param>
        /// <param name="newFileName">New file name.</param>
        /// <param name="includePrefix">true: the fileName will be attache a prefix string</param>
        /// <returns>If success this function will return OK string</returns>
        public string RenameFile(string oldFileName, string newFileName, bool includePrefix)
        {         
            try
            {
                string secretKey = ConfigurationManager.AppSettings["SecretKey"];
                string imageHost = ConfigurationManager.AppSettings["ImageServer"];
                string prefix = ConfigurationManager.AppSettings["Prefix"];

                string keyRename = ConfigurationManager.AppSettings["keyRename"];
                DownloadExpress down = new DownloadExpress(imageHost + keyRename + "?secret_key=" + secretKey + "&from=" + (includePrefix ? string.Format("{0}/{1}", prefix, oldFileName) : oldFileName) + 
                                                            "&to=" + (includePrefix ? string.Format("{0}/{1}", prefix, newFileName) : newFileName));
                string ad = down.GetHtmlData();
                return ad;
            }
            catch (Exception ex)
            {
                throw ex;                
            }
        }

        /// <summary>
        /// Get information of a file
        /// </summary>
        /// <param name="fileName">The file need to get information</param>
        /// <param name="includePrefix">true: the fileName will be attache a prefix string</param>
        /// <returns>Return an object contain informations of this file</returns>
        public ChannelvnFileInfo GetFileInfo(string fileName, bool includePrefix)
        {
            try
            {
                string secretKey = ConfigurationManager.AppSettings["SecretKey"];
                string keyGetInfo = ConfigurationManager.AppSettings["keyGetInfo"];
                string imageHost = ConfigurationManager.AppSettings["ImageServer"];
                string prefix = ConfigurationManager.AppSettings["Prefix"];
                DownloadExpress down = new DownloadExpress(imageHost + keyGetInfo + "?secret_key=" + secretKey + "&filename=" + (includePrefix ? string.Format("{0}/{1}", prefix, fileName) : fileName));
                string ret = down.GetHtmlData();
                return Utils.ConvertToFileObj(ret);
            }
            catch (Exception ex) {
                throw ex;                
            }
        }

        /// <summary>
        /// Return the link of thumb image
        /// </summary>
        /// <param name="fileName">The file need to get thumb image.</param>
        /// <param name="width">width of thumb image</param>
        /// <param name="height">height of thumb image</param>
        /// <returns>Return the link of thumb image</returns>
        public string GetThumbImage(string fileName, int width, int height) {
            try
            {
                string keyThumb = ConfigurationManager.AppSettings["keyThumb"];
                string readImageHost = ConfigurationManager.AppSettings["ReadImageServer"];
                string baseFolder = Utils.GetFolder(fileName, readImageHost);
                string ret = readImageHost + keyThumb + "/" + width + "_" + height + "/" + baseFolder;
                return ret;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Return the link of thumb image
        /// </summary>
        /// <param name="fileName">The file need to get thumb image.</param>
        /// <param name="width">width of thumb image</param>
        /// <returns>Return the link of thumb image</returns>
        public string GetThumbImage(string fileName, int width)
        {
            try
            {
                string keyThumb = ConfigurationManager.AppSettings["keyThumbWidth"];
                string readImageHost = ConfigurationManager.AppSettings["ReadImageServer"];
                string baseFolder = Utils.GetFolder(fileName, readImageHost);
                string ret = readImageHost + keyThumb + "/" + width + "/" + baseFolder;
                return ret;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}
